
import {AggregateOptions} from '@redis/search/dist/commands/AGGREGATE'
import {Subarea} from 'knex/types/tables'
import {AggregateGroupByReducers, AggregateSteps, SchemaFieldTypes} from 'redis'
import {redisSQLDatabase} from 'TYPE'
import {cache, createIndex} from '../cache'
import {RedisSearchLanguages} from "@redis/search/dist/commands"
import knex from '../sql'
import {postDB} from './post.db'

declare module 'knex/types/tables' {
    interface Subarea {
        id: number
        name: string
        need_moderate: boolean
        description: string
        type: number
    }
    interface Tables {
        subareas: Subarea
    }
}

class SubareaDB implements redisSQLDatabase {
    async getSubareaById(id: number) {
        let key = `subarea:${id}`
        let subarea: Subarea = await cache.json.get(key) as any
        
        return subarea
    }
    allSubareas = {}
    async loadSubareaById(id: number) {
        let key = `subarea:${id}`
        let subarea: Subarea = null
        await knex('subareas').select().where({id}).first().then(s => {
            if (s) {
                subarea = s
                cache.json.set(key, '$', subarea as any)
                subareaDB.allSubareas[subarea.id] = subarea
            }
        })
        return subarea
    }
    indexName = 'idx:subareas' as const
    async initIndex(del = false) {
        if (del) {
            await cache.ft.dropIndex(this.indexName)
        }
        await createIndex(this.indexName, {
            '$.name': {
                type: SchemaFieldTypes.TAG as any,
                AS: 'name'
            },
            '$.type': {
                type: SchemaFieldTypes.TAG as any,
                AS: 'type'
            },
            '$.id': {
                type: SchemaFieldTypes.NUMERIC as any,
                SORTABLE: true,
                AS: 'id'
            },
        }, {
            ON: 'JSON', PREFIX: 'subarea:', LANGUAGE: RedisSearchLanguages.CHINESE
        })
    }
    async getSubareas(type: number, paged: number, posts_per_page: number) {
        let subareas = []
        let res = await cache.ft.search(this.indexName, `(@type:{${type}})`, {
            SORTBY: {BY: "id" as any, DIRECTION: 'ASC'},
            LIMIT: {from: (paged - 1) * posts_per_page, size: posts_per_page},
        })

        for (const v of res.documents) {
            subareas.push(v.value as any)
        }
        return subareas
    }
    async loadAll() {
        await cache.keys('subarea:*').then(async (keys) => {
            for (const key of keys) {
                await cache.del(key)
            }
        })
        await knex('subareas').select().then(ss => {
            for (let subarea of ss) {
                (subarea as any).topic_num = 0;
                (subarea as any).post_num = 0;
                (subarea as any).type = subarea.type + '';
                let key = `subarea:${subarea.id}`
                cache.json.set(key, '$', subarea as any)
                subareaDB.allSubareas['' + subarea.id] = subarea
            }
        })
    }
    async afterLoad() {

        // let option: AggregateOptions
        // option = {
        //     STEPS: [{
        //         type: AggregateSteps.GROUPBY,
        //         properties: "@subarea",
        //         REDUCE: [{
        //             type: AggregateGroupByReducers.COUNT,
        //             AS: 'post_count'
        //         },]
        //     }]
        // }
        // count all the topic and post in every subareas.
        await cache.ft.AGGREGATE(postDB.indexName, "(@deleted:{0})", {
            STEPS: [{
                type: AggregateSteps.GROUPBY,
                properties: ["@subarea", "@type"],
                REDUCE: [{
                    type: AggregateGroupByReducers.COUNT,
                    AS: 'post_count'
                }]
            }]
        }).then(async (ret) => {
            for (let item of ret.results) {
                if (item.subarea != 'null') {
                    if (item.type == '1') {
                        await cache.json.numIncrBy(`subarea:${item.subarea}`, '$.topic_num', Number(item.post_count))
                        await cache.json.numIncrBy(`subarea:${item.subarea}`, '$.post_num', Number(item.post_count))
                    }
                    if (item.type == '2') {
                        await cache.json.numIncrBy(`subarea:${item.subarea}`, '$.post_num', Number(item.post_count))
                    }
                }
            }
        })

    }
}
export const subareaDB = new SubareaDB()
